
#include <iostream>
#include <fstream>
#include <vector>

#include "../mainctrl.h"
#include "../item/CItemMgr.h"
#include "../item/CScrollConfig.h"
#include "../storage/CUserStorage.h"
#include "../online/onlineuser.h"
#include "CUserEquip.h"
#include "CEquipMgr.h"
#include "pb_cfg_equip.pb.h"
#include "pb_cfg_potential.pb.h"
#include "MsgStorage.pb.h"
#include "MsgComm.pb.h"
#include "commmsg.h"
#include "MsgEquipInfo.pb.h"
#include "../storage/CStorageMgr.h"

int CEquipMgr::InitData(CUserEquip& stUserEquip, unsigned int uiGID, CEquipData & stEquipData)
{
    stUserEquip.Clear();
    stUserEquip._uiGID = uiGID;
    stUserEquip._uiEquipSeqId = stEquipData._uiEquipSeqId;
    for (int i = 0;  i < stEquipData._astEquipData.Size(); i++)
    {
        CSingleEquip & stData = stEquipData._astEquipData[i];
        uint64 ui64EquipKey = MakeEquipKey(stUserEquip._uiGID, stData._uiEquipID);
        int iIndex = stUserEquip._stEquipHash.HashFind(ui64EquipKey);   //保证装备ID唯一
        if (iIndex >= 0)
        {
            CT_ERROR(("Equip already existed. gid: %u, equipid: %u",stUserEquip._uiGID,stData._uiEquipID));
            continue ;
        }

        iIndex = stUserEquip._stEquipHash.HashAlloc(ui64EquipKey);
        if (iIndex < 0)
        {
            CT_ERROR(("Equip is full. gid: %u, equipid: %u, index: %u", stUserEquip._uiGID,stData._uiEquipID, iIndex));
            return ERROR_EQUIP_FULL;
        }

        stUserEquip._stEquipHash[iIndex] = stData;
    }

    return 0;
}

int CEquipMgr::GetData(CUserEquip& stUserEquip, CEquipData & stData)
{
    stData.Clear();
    stData._uiEquipSeqId = stUserEquip._uiEquipSeqId;
    T_USER_EQUIP_HASH & stEquipHash = stUserEquip._stEquipHash;
    for (int iIndex = stEquipHash.GetHeadIndex();
        iIndex >= 0; iIndex = stEquipHash.GetNextIndex(iIndex))
    {
        int iRet = stData._astEquipData.AddOneItem(stEquipHash[iIndex]);
        if (iRet < 0)
        {
            CT_ERROR(("GetData. gid: %u, equipid: %u, index: %u", stUserEquip._uiGID,stEquipHash[iIndex]._uiEquipID, iIndex));
            return iRet;
        }
    }

    return 0;
}

int CEquipMgr::LoadEquipConfig(pb_cfg_equip & stEquipPbCfg)
{
    for (int i = 0; i < stEquipPbCfg.equip_config_rows_size(); ++i)
    {
        const pb_cfg_equip_pb_cfg_equip_config_unit & stEquipPbCfgUnit
            = stEquipPbCfg.equip_config_rows(i);

        CEquipConfigData stConfigData;

        stConfigData._usEquipConfigID = stEquipPbCfgUnit.config_id();
        stConfigData._ucEquipLevel = stEquipPbCfgUnit.equip_level();
        stConfigData._usUseLevel = stEquipPbCfgUnit.use_min_level();
        stConfigData._ucEquipPos = stEquipPbCfgUnit.equip_pos();
        stConfigData._ucCareerType = stEquipPbCfgUnit.career_limit();
        stConfigData._szDropItemSubType.Set("%s", stEquipPbCfgUnit.dropitem_subtype().c_str());

        stConfigData._uiSilverBuyPrice = stEquipPbCfgUnit.silver_buy_price();
        stConfigData._uiGoldBuyPrice = stEquipPbCfgUnit.gold_buy_price();
        stConfigData._uiSilverSellPrice = stEquipPbCfgUnit.silver_sell_price();

        stConfigData._ucBaseAttrType1 = stEquipPbCfgUnit.attr_type1();
        stConfigData._uiBaseAttrValue1 = stEquipPbCfgUnit.attr_value1();
        stConfigData._usAttrStrthenValue1 = stEquipPbCfgUnit.attr_strengthen_value1();

        stConfigData._ucBaseAttrType2 = stEquipPbCfgUnit.attr_type2();
        stConfigData._uiBaseAttrValue2 = stEquipPbCfgUnit.attr_value2();
        stConfigData._usAttrStrthenValue2 = stEquipPbCfgUnit.attr_strengthen_value2();

        stConfigData._ucSuitID       = stEquipPbCfgUnit.suit_id();
        stConfigData._uiBaseFightCap = stEquipPbCfgUnit.base_fight_capacity();
        stConfigData._uicCrystalHoleNum = stEquipPbCfgUnit.crystal_hole_num();
        stConfigData._ucCrystalPermLevel = stEquipPbCfgUnit.crystal_perm_level();
        stConfigData._usScrollId         =  stEquipPbCfgUnit.scroll_id();
        stConfigData._uiInstanceType = (unsigned int)(stEquipPbCfgUnit.default_drop_instance_type() & 0x7FFFFFFF);
        stConfigData._uiInstanceId = (unsigned int)(stEquipPbCfgUnit.default_drop_instance_id() & 0x7FFFFFFF);

        stConfigData._iRefineAttrCount = stEquipPbCfgUnit.refine_attr_count();
        stConfigData._iRefineUseMaterial = stEquipPbCfgUnit.refine_use_material();
        stConfigData._iMaxBlessLevel = stEquipPbCfgUnit.max_bless_level();

        stConfigData._bCanAutoSellInIns = (stEquipPbCfgUnit.auto_sell_in_ins() == 1);

        //有效的套装ID必须大于0
        if (stConfigData._ucSuitID > 0)
        {
            CEquipSuiteCfg stSuitCfg;
            if (GetSuiteConfig(stConfigData._ucSuitID, stSuitCfg) != RET_OK)
            {
                CT_ERROR(("%d", stConfigData._usEquipConfigID));
                return RET_SYSTEM_FAIL;
            }
        }

        int iRet = AddConfigData(stConfigData);
        CHECK_RETURN(iRet);
    }

    return 0;
}

int CEquipMgr::LoadPotentialConfig(pb_cfg_potential & stPbCfg)
{
    for (int i = 0; i < stPbCfg.poten_rows_size(); ++i)
    {
        const pb_cfg_potential_pb_cfg_poten_unit & stCfgUnit = stPbCfg.poten_rows(i);

        CCystalPotentialCfg stCfg;
        stCfg._iCoff = stCfgUnit.conf();
        stCfg._iUpgradeExp = stCfgUnit.exp();

        unsigned char ucLevel = stCfgUnit.level();
        int iRet = _stEquipConfig.AddPotentialCfg(ucLevel, stCfg);
        if (iRet)
        {
            CT_ERROR(("%d, %d, %d, %d", iRet, ucLevel, stCfg._iCoff, stCfg._iUpgradeExp));
            return iRet;
        }
    }

    if (0 == _stEquipConfig._ucMaxPotentialLevel)
    {
        CT_ERROR(("%d", _stEquipConfig._ucMaxPotentialLevel));
        return ERROR_WRONG_POTENTIAL_CONFIG;
    }

    return 0;
}

int CEquipMgr::LoadSuiteConfig(pb_cfg_equip & stEquipPbCfg)
{
    //读取套装配置
    for (int i = 0; i < stEquipPbCfg.suit_config_rows_size(); ++i)
    {
        const pb_cfg_equip_pb_cfg_suit_config_unit & stEquipPbCfgUnit
            = stEquipPbCfg.suit_config_rows(i);

        CEquipSuiteCfg stConfigData;

        stConfigData._ucSuiteId = stEquipPbCfgUnit.suit_id();
        stConfigData._ucSuiteAttrType1 = stEquipPbCfgUnit.attr_type1();
        stConfigData._uiSuiteAttrValue1 = stEquipPbCfgUnit.attr_value1();
        stConfigData._ucSuiteAttrType2 = stEquipPbCfgUnit.attr_type2();
        stConfigData._uiSuiteAttrValue2 = stEquipPbCfgUnit.attr_value2();
        stConfigData._ucSuiteAttrType3 = stEquipPbCfgUnit.attr_type3();
        stConfigData._uiSuiteAttrValue3 = stEquipPbCfgUnit.attr_value3();

        int iRet = AddSuiteConfig(stConfigData);
        CHECK_RETURN(iRet);
    }

    return 0;
}

int CEquipMgr::LoadStrengthConfig(pb_cfg_equip & stEquipPbCfg)
{
    //读取强化价格表
    for (int i = 0; i < stEquipPbCfg.strength_price_config_rows_size(); ++i)
    {
        const pb_cfg_equip_pb_cfg_strength_price_config_unit & stEquipPbCfgUnit
            = stEquipPbCfg.strength_price_config_rows(i);

        CEquipStrengthCfg stConfigData;
        stConfigData._stKey._usEquipLevel = stEquipPbCfgUnit.equip_level();
        stConfigData._stKey._usCurStrengthLevel = stEquipPbCfgUnit.cur_strength_level();
        stConfigData._iStrengthPrice = stEquipPbCfgUnit.strength_price();
        stConfigData._iSellPrice = stEquipPbCfgUnit.sell_price();

        int iRet = AddStrengthConfig(stConfigData);
        CHECK_RETURN(iRet);
    }

    return 0;
}

int CEquipMgr::LoadConfig(const char* szLogPath, const char* szPotenPath)
{
    int iRet = 0;

    if (szLogPath == NULL)
    {
        CT_ERROR(("Task Log Path is null"));
        return RET_SYSTEM_FAIL;
    }

    pb_cfg_equip stEquipPbCfg;
    std::fstream stFileInput(szLogPath, std::ios::in | std::ios::binary);
    if (!stEquipPbCfg.ParseFromIstream(&stFileInput))
    {
        CT_ERROR(("Failed to Parse EquipCfg!"));
        return RET_SYSTEM_FAIL;
    }

    iRet = LoadSuiteConfig(stEquipPbCfg);
    CHECK_RETURN(iRet);

    iRet = LoadEquipConfig(stEquipPbCfg);
    CHECK_RETURN(iRet);

    iRet = LoadStrengthConfig(stEquipPbCfg);
    CHECK_RETURN(iRet);

    pb_cfg_potential stPotenPbCfg;
    std::fstream stPotenInput(szPotenPath, std::ios::in | std::ios::binary);
    if (!stPotenPbCfg.ParseFromIstream(&stPotenInput))
    {
        CT_ERROR(("Failed to Parse pb_cfg_potential!"));
        return RET_SYSTEM_FAIL;
    }

    iRet = LoadPotentialConfig(stPotenPbCfg);
    CHECK_RETURN(iRet);

    //洗练和祝福
    for (int i = 0; i < stEquipPbCfg.refine_and_bless_rows_size(); ++i)
    {
        const pb_cfg_equip_pb_cfg_refine_and_bless_unit & stCfgUnit = stEquipPbCfg.refine_and_bless_rows(i);

        iRet = _stRefineAndBlessConfig.AddConfig(stCfgUnit);
        CHECK_RETURN(iRet);
    }

    return 0;
}


int CEquipMgr::AddConfigData(CEquipConfigData& stConfigData)
{
    return _stEquipConfig.AddConfigData(stConfigData);
}

int CEquipMgr::GetConfigData(unsigned int uiEquipId, CEquipConfigData& stConfigData)
{
    unsigned short usConfigId;
    GetConfigIdByEquipId(uiEquipId, usConfigId);
    return _stEquipConfig.GetConfigData(usConfigId, stConfigData);
}

int CEquipMgr::GetConfigData(CDropItemSubTypeConfigData::T_DROP_ITEM_SUBTYPE_CONFIG_KEY& szKey,
                                CEquipConfigData& stConfigData)
{
    return _stEquipConfig.GetConfigData(szKey, stConfigData);
}


int CEquipMgr::AddSuiteConfig(CEquipSuiteCfg & stConfigData)
{
    return _stEquipConfig.AddSuiteCfg(stConfigData);
}

int CEquipMgr::GetSuiteConfig(unsigned char ucSuiteID, CEquipSuiteCfg& stConfigData)
{
    return _stEquipConfig.GetSuiteConfig(ucSuiteID, stConfigData);
}

int CEquipMgr::AddStrengthConfig(CEquipStrengthCfg & stConfigData)
{
    return _stEquipConfig.AddStrengthCfg(stConfigData);
}

int CEquipMgr::GetStrengthConfig(CStrengthCfgKey & stKey, CEquipStrengthCfg& stConfigData)
{
    return _stEquipConfig.GetStrengthConfig(stKey, stConfigData);
}

int CEquipMgr::GetScrollEquipCfgId(unsigned short usScrollID, unsigned short &usEquipConfigID)
{
    return _stEquipConfig.GetScorllEquipId(usScrollID, usEquipConfigID);
}

int CEquipMgr::GetEquipStrengthPrice(unsigned short usEquipConfigID, unsigned char ucCurStrength, int& iSilver)
{
    CEquipConfigData stEquipConfig;
    GetConfigData(usEquipConfigID, stEquipConfig);

    //读配置
    CEquipConfigData   stConfigData;
    CEquipStrengthCfg  stStrengthCfg;
    int iRet = _stEquipConfig.GetConfigData(usEquipConfigID, stConfigData);
    CHECK_RETURN(iRet);

    stStrengthCfg._stKey._usEquipLevel = stConfigData._ucEquipLevel;
    stStrengthCfg._stKey._usCurStrengthLevel = ucCurStrength;
    iRet = _stEquipConfig.GetStrengthConfig(stStrengthCfg._stKey, stStrengthCfg);
    CHECK_RETURN(iRet);

    iSilver = (stStrengthCfg._iStrengthPrice * (_stEquipConfig._stEquipPriceCoef[stConfigData._ucEquipPos]))/10;
    return 0;
}


//为初次登陆的用户分配装备
int CEquipMgr::AllocUserFirstEquip(unsigned char ucCareer, CUserEquip& stUserEquip, CUserStorage & stUserStorage)
{
    CRoleConfigMgr & m_stRoleConfigMgr = CMainCtrl::m_pstMain->m_stRoleConfigMgr;
    int iIndex = m_stRoleConfigMgr.FindRoleInitCfg(ucCareer);
    if (iIndex < 0)
    {
        return ERROR_ROLE_INIT_EMPTY_CFG;
    }
    CRoleInitCfgData& stRoleInit = m_stRoleConfigMgr.GetRoleInitCfg(iIndex);

    int iRet = 0;
    unsigned int uiEquipId = 0;
    if (stRoleInit._usHelmetId)
    {
        iRet = AddEquip(stUserEquip, stRoleInit._usHelmetId, stUserStorage, uiEquipId);
        if (iRet)
        {
            CT_ERROR(("AllocFirstLoginEquip, AddEquip, equip_cfg_id: %u, ret: %u", stRoleInit._usHelmetId, iRet));
            return iRet;
        }
    }

    if (stRoleInit._usColthId)
    {
        iRet = AddEquip(stUserEquip, stRoleInit._usColthId, stUserStorage, uiEquipId);
        if (iRet)
        {
            CT_ERROR(("AllocFirstLoginEquip, AddEquip, equip_cfg_id: %u, ret: %u", stRoleInit._usColthId, iRet));
            return iRet;
        }
    }

    if (stRoleInit._usWeaponId)
    {
        iRet = AddEquip(stUserEquip, stRoleInit._usWeaponId, stUserStorage, uiEquipId);
        if (iRet)
        {
            CT_ERROR(("AllocFirstLoginEquip, AddEquip, equip_cfg_id: %u, ret: %u", stRoleInit._usWeaponId, iRet));
            return iRet;
        }
    }

    if (stRoleInit._usShoeId)
    {
        iRet = AddEquip(stUserEquip, stRoleInit._usShoeId, stUserStorage, uiEquipId);
        if (iRet)
        {
            CT_ERROR(("AllocFirstLoginEquip, AddEquip, equip_cfg_id: %u, ret: %u", stRoleInit._usShoeId, iRet));
            return iRet;
        }
    }

    return 0;
}

int CEquipMgr::GetEquipAttr(unsigned short usEquipConfigID, unsigned short usStrengthLevel, MsgEquipAttr &stEquipAttr)
{
    CSingleEquipAttr stSingleEquipAttr;
    int iRet = GetEquipAttr(usEquipConfigID, usStrengthLevel, stSingleEquipAttr);
    CHECK_RETURN(iRet);

    stEquipAttr.Clear();
    stEquipAttr.set_strength_level(usStrengthLevel);
    for (int i = 0; i < stSingleEquipAttr._stSingleEquipAttr.Size(); i++)
    {
        MsgTypeValuePair * pstTypeValue = stEquipAttr.add_fight_attrs();

        pstTypeValue->set_type(stSingleEquipAttr._stSingleEquipAttr[i]._ucType);
        pstTypeValue->set_value(stSingleEquipAttr._stSingleEquipAttr[i]._iValue);
    }

    return 0;
}

int CEquipMgr::GetEquipAttr(CUserEquip& stUserEquip, unsigned int uiPartnerId, CPlayerAttr& stEquipAttr)
{
    for (int iIndex = stUserEquip._stEquipHash.GetHeadIndex();
        iIndex >= 0;
        iIndex = stUserEquip._stEquipHash.GetNextIndex(iIndex))
    {
        CSingleEquip & stSingleEquip = stUserEquip._stEquipHash[iIndex];

        if (uiPartnerId != stSingleEquip._uiPartnerId)
        {
            continue;
        }

        CSingleEquipAttr stSingleEquipAttr;
        int iRet = GetEquipAttr(stSingleEquip._usEquipConfigID, stSingleEquip._usStrengthenLevel, stSingleEquipAttr);
        if (iRet)
        {
            CT_ERROR((""));
            continue;
        }

		for (int k = 0; k < stSingleEquipAttr._stSingleEquipAttr.Size(); ++k)
		{
        	stEquipAttr.AddAttr(stSingleEquipAttr._stSingleEquipAttr[k]._ucType,
                                stSingleEquipAttr._stSingleEquipAttr[k]._iValue);
		}

        //洗练和祝福属性
        CPlayerAttr stRefineAndBlessAttr;
        GetRefineAndBlessAttr(stSingleEquip, stRefineAndBlessAttr);
        stEquipAttr += stRefineAndBlessAttr;
    }

    return 0;
}

//获取魔晶属性提升比例
int CEquipMgr::GetCrystalAttr(CUserEquip& stUserEquip, unsigned int uiPartnerId, bool bOnlyBase, CPlayerAttr& stPlayerAttr)
{
    int iRet;
    CTArray<CAttrPair, MAX_CRYSTAL_ATTR_TYPE>  stCystal;   //key保存魔晶的属性, value保存提升的比例
    CTArray<CAttrPair, MAX_EQUIP_CRYSTAL_NUM>  stEquip;
    for (int iIndex = stUserEquip._stEquipHash.GetHeadIndex();
        iIndex >= 0;
        iIndex = stUserEquip._stEquipHash.GetNextIndex(iIndex))
    {
        CSingleEquip & stSingleEquip = stUserEquip._stEquipHash[iIndex];
        if (uiPartnerId != stSingleEquip._uiPartnerId)
        {
            continue;
        }

        stEquip.Clear();
        for (int i = 0; i < MAX_EQUIP_CRYSTAL_NUM; ++i)
        {
            CAttrPair stSingleCrystalAttr;
            if (0 != stSingleEquip._aucCrystalID[i])
            {
                iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetCrystalAttr(stSingleEquip._aucCrystalID[i], stSingleCrystalAttr);
                CHECK_RETURN(iRet);
#if 0
                unsigned char ucAttrType = stSingleCrystalAttr._ucType;
                if (true == bOnlyBase)
                {
                    if (true == CPlayerAttr::IsBaseAttr(ucAttrType))
                    {
                        stEquip.AddOneItem(stSingleCrystalAttr);
                    }
                }
                else
                {
                    if (false == CPlayerAttr::IsBaseAttr(ucAttrType))
                    {
                        stEquip.AddOneItem(stSingleCrystalAttr);
                    }
                }
#endif          
                stEquip.AddOneItem(stSingleCrystalAttr);
            }
        }

        //叠加装备上的魔晶属性到一起
        for (int i = 0; i < stEquip.Size(); i++)
        {
            bool bNewAttr = true;
            for (int j = 0; j < stCystal.Size(); j++)
            {
                if (stEquip[i]._ucType == stCystal[j]._ucType)
                {
                    stCystal[j]._iValue += stEquip[i]._iValue;
                    bNewAttr = false;
                    break;
                }
            }

            if (bNewAttr)
            {
                stCystal.AddOneItem(stEquip[i]);
            }
        }
    }

    //修改玩家身上的属性
    int iAttrValue = 0;
    for (int i = 0; i < stCystal.Size(); i++)
    {
        stPlayerAttr.GetAttr(stCystal[i]._ucType, iAttrValue);
        if (EXT_ATTR_REACT_INJURY == stCystal[i]._ucType
            || EXT_ATTR_PENETRATE == stCystal[i]._ucType
            || EXT_ATTR_TREATMENT == stCystal[i]._ucType)
        {
            iAttrValue += stCystal[i]._iValue;
        }
        else
        {
#if 0
            iAttrValue += ((iAttrValue * stCystal[i]._iValue) / COMM_MOD);
#endif
            iAttrValue += stCystal[i]._iValue;
        }
        
        stPlayerAttr.SetAttr(stCystal[i]._ucType, iAttrValue);
    }

    return 0;
}

int CEquipMgr::GetSingleEquipSuiteAttr (CUserEquip& stUserEquip, unsigned int uiEquipId, unsigned char & ucSuiteId, T_EQUIP_SUITE_ATTR & stSuiteAttr)
{
    CSingleEquip stEquip;
    int iRet = GetEquip(stUserEquip, uiEquipId, stEquip);
    CHECK_RETURN(iRet);

    CEquipConfigData stEquipConfig;
    iRet = GetConfigData(stEquip._usEquipConfigID, stEquipConfig);
    CHECK_RETURN(iRet);
    ucSuiteId = stEquipConfig._ucSuitID;

    stSuiteAttr.Clear();
    if (!stEquip.IsWeared())
    {
        return 0;
    }

    unsigned char ucSuiteCnt = 1;
    for (int iIndex = stUserEquip._stEquipHash.GetHeadIndex();
        iIndex >= 0;
        iIndex = stUserEquip._stEquipHash.GetNextIndex(iIndex))
    {
        CSingleEquip & stSingleEquip = stUserEquip._stEquipHash[iIndex];

        if (stEquip._uiPartnerId != stSingleEquip._uiPartnerId
            || (stEquip._uiEquipID == uiEquipId))
        {
            continue;
        }

        CEquipConfigData stEquipConfig;
        iRet = GetConfigData(stSingleEquip._usEquipConfigID, stEquipConfig);
        CHECK_RETURN(iRet);

        if (stEquipConfig._ucSuitID == ucSuiteId)
        {
            ucSuiteCnt += 1;
        }
    }

    //从配置文件读取属性
    CEquipSuiteCfg stSuiteConfig;
    iRet = GetSuiteConfig(ucSuiteId, stSuiteConfig);
    CHECK_RETURN(iRet);

    CAttrPair stAttr;
    if (ucSuiteCnt > 1)
    {
        stAttr._ucType = stSuiteConfig._ucSuiteAttrType1;
        stAttr._iValue = stSuiteConfig._uiSuiteAttrValue1;
        stSuiteAttr.AddOneItem(stAttr);
    }

    if (ucSuiteCnt > 2)
    {
        stAttr._ucType = stSuiteConfig._ucSuiteAttrType2;
        stAttr._iValue = stSuiteConfig._uiSuiteAttrValue2;
        stSuiteAttr.AddOneItem(stAttr);
    }

    if (ucSuiteCnt > 3)
    {
        stAttr._ucType = stSuiteConfig._ucSuiteAttrType3;
        stAttr._iValue = stSuiteConfig._uiSuiteAttrValue3;
        stSuiteAttr.AddOneItem(stAttr);
    }

    return 0;
}

int CEquipMgr::GetSuiteAttr(CUserEquip& stUserEquip, unsigned int uiPartnerId, CPlayerAttr& stSuiteAttr)
{
    int iRet;
    CTArray<CAttrPair, MAX_EQUIP_ON_ROLE>  stSuite;   //key保存套装ID, value保存套装的件数
    for (int iIndex = stUserEquip._stEquipHash.GetHeadIndex();
        iIndex >= 0;
        iIndex = stUserEquip._stEquipHash.GetNextIndex(iIndex))
    {
        CSingleEquip & stSingleEquip = stUserEquip._stEquipHash[iIndex];

        if ((!stSingleEquip.IsWeared())
            || (uiPartnerId != stSingleEquip._uiPartnerId))
        {
            continue;
        }

        CEquipConfigData stEquipConfig;
        iRet = GetConfigData(stSingleEquip._usEquipConfigID, stEquipConfig);
        CHECK_RETURN(iRet);

        if (stEquipConfig._ucSuitID == 0)
        {
            continue;
        }

        bool bNewSuite = true;
        for (int i = 0; i < stSuite.Size(); i++)
        {
            if (stEquipConfig._ucSuitID == stSuite[i]._ucType)
            {
                stSuite[i]._iValue += 1;
                bNewSuite = false;
                break;
            }
        }

        if (bNewSuite)
        {
            CAttrPair stNewSuite;
            stNewSuite._ucType = stEquipConfig._ucSuitID;
            stNewSuite._iValue = 1;
            stSuite.AddOneItem(stNewSuite);
        }
    }

    //从配置文件读取属性
    for (int i = 0; i < stSuite.Size(); i++)
    {
        if (stSuite[i]._ucType == 0)
        {
            continue;
        }

        CEquipSuiteCfg stSuiteConfig;
        iRet = GetSuiteConfig(stSuite[i]._ucType, stSuiteConfig);
        if (iRet)
        {
            CT_ERROR(("%d, %d", stSuite[i]._ucType, iRet));
            continue;
        }

        CT_TRACE(("gid: %u, uiPartnerId: %u, suite: %d, cnt: %d", stUserEquip._uiGID, uiPartnerId, stSuite[i]._ucType, stSuite[i]._iValue));

        if (stSuite[i]._iValue > 1)
        {
            stSuiteAttr.AddAttr(stSuiteConfig._ucSuiteAttrType1, stSuiteConfig._uiSuiteAttrValue1);
        }

        if (stSuite[i]._iValue > 2)
        {
            stSuiteAttr.AddAttr(stSuiteConfig._ucSuiteAttrType2, stSuiteConfig._uiSuiteAttrValue2);
        }

        if (stSuite[i]._iValue > 3)
        {
            stSuiteAttr.AddAttr(stSuiteConfig._ucSuiteAttrType3, stSuiteConfig._uiSuiteAttrValue3);
        }
    }

    return 0;
}


int CEquipMgr::GetPotenAttr (CUserEquip& stUserEquip, unsigned char ucPotenLevel, unsigned int uiPartnerId, CPlayerAttr& stPotenAttr)
{
    int iRet = RET_OK;
    int iCoff = _stEquipConfig.GetPotentialCoff (ucPotenLevel);    

    for (int iIndex = stUserEquip._stEquipHash.GetHeadIndex();
        iIndex >= 0;
        iIndex = stUserEquip._stEquipHash.GetNextIndex(iIndex))
    {
        CSingleEquip & stSingleEquip = stUserEquip._stEquipHash[iIndex];

        if ((!stSingleEquip.IsWeared())
            || (uiPartnerId != stSingleEquip._uiPartnerId))
        {
            continue;
        }

        for (int i = 0; i < MAX_EQUIP_CRYSTAL_NUM; ++i)
        {
            CAttrPair stSingleCrystalAttr;
            if (0 != stSingleEquip._aucCrystalID[i])
            {
                iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetPotenAttrAdd(stSingleEquip._aucCrystalID[i], stSingleCrystalAttr);
                if (iRet)
                {
                    CT_ERROR(("%d, %d", iRet, stSingleEquip._aucCrystalID[i]));
                }
                
                stPotenAttr.AddAttr(stSingleCrystalAttr._ucType, stSingleCrystalAttr._iValue * iCoff);
            }
        }
    }

    return 0;
}

int CEquipMgr::GetRefineAndBlessAttr(CSingleEquip& stSingleEquip, CPlayerAttr& stEquipAttr)
{
    int iRet = 0;
    stEquipAttr.Clear();

    CEquipConfigData stEquipConfigData;
    iRet = GetConfigData(stSingleEquip._usEquipConfigID, stEquipConfigData);
    CHECK_RETURN(iRet);

    //洗练和祝福属性
    if (stEquipConfigData._iRefineAttrCount > 0) //可洗练的装备
    {
        for (int i = 0; i < stEquipConfigData._iRefineAttrCount
            && stSingleEquip._stRefineAndBlessStats[i] > 0; ++i)
        {
            unsigned char ucRefineAttrID = stSingleEquip._stRefineAndBlessStats[i] / 10;
            unsigned char ucRefineLevel = stSingleEquip._stRefineAndBlessStats[i] % 10 + 1;

            stEquipAttr.AddAttr(_stRefineAndBlessConfig._astRefineAttrChange[ucRefineAttrID - 1],
                        _stRefineAndBlessConfig._astRefineAttrValues[ucRefineAttrID - 1][ucRefineLevel - 1]);
        }
    }
    else if (stEquipConfigData._iMaxBlessLevel > 0
        && stSingleEquip._stRefineAndBlessStats[1] > 0) //可祝福且已祝福的装备
    {
        unsigned char ucBlessStat = stSingleEquip._stRefineAndBlessStats[0];
        unsigned char ucBlessLevel = stSingleEquip._stRefineAndBlessStats[1];
        int iValue = _stRefineAndBlessConfig._astBlessAttrValues[ucBlessLevel - 1];

        //属性顺序：智力、体力、力量、敏捷
        CTArray<unsigned char, MAX_EQUIP_BLESS_ATTR_PER_EQUIP> astBlessAttrID;
        astBlessAttrID.AddOneItem(BASE_ATTR_INT);
        astBlessAttrID.AddOneItem(BASE_ATTR_VIT);
        astBlessAttrID.AddOneItem(BASE_ATTR_STR);
        astBlessAttrID.AddOneItem(BASE_ATTR_AGI);

        for (int i = 0; i < MAX_EQUIP_BLESS_ATTR_PER_EQUIP; ++i)
        {
            if (ucBlessStat & 1 << i)
            {
                stEquipAttr.AddAttr(astBlessAttrID[i], iValue);
            }
        }
    }
    
    return 0;
}


int CEquipMgr::GetEquipAttr(unsigned short usEquipConfigID, unsigned short usStrengthLevel, CSingleEquipAttr &stEquipAttr)
{
    CEquipConfigData stEquipConfigData;
    int iRet = GetConfigData(usEquipConfigID, stEquipConfigData);
    CHECK_RETURN(iRet);

    stEquipAttr._stSingleEquipAttr.Clear();
    CAttrPair stAttrPair;
    stAttrPair._ucType = stEquipConfigData._ucBaseAttrType1;
    stAttrPair._iValue = stEquipConfigData._uiBaseAttrValue1 + (usStrengthLevel - 1)* stEquipConfigData._usAttrStrthenValue1;
    if (0 != stAttrPair._ucType)
    {
        iRet = stEquipAttr._stSingleEquipAttr.AddOneItem(stAttrPair);
        if (iRet < 0)
        {
            return iRet;
        }
    }

    stAttrPair._ucType = stEquipConfigData._ucBaseAttrType2;
    stAttrPair._iValue = stEquipConfigData._uiBaseAttrValue2 + (usStrengthLevel - 1) * stEquipConfigData._usAttrStrthenValue2;
    if (0 != stAttrPair._ucType)
    {
        iRet = stEquipAttr._stSingleEquipAttr.AddOneItem(stAttrPair);
        if (iRet < 0)
        {
            return iRet;
        }
    }

    return 0;
}


int CEquipMgr::GetEquipList(CUserEquip& stUserEquip, unsigned int uiRoleId, T_EQUIP_ITEMS &astEquip)
{
    int iRet = 0;

    astEquip.Clear();
    for (int i = stUserEquip._stEquipHash.GetHeadIndex();
        i >= 0; i = stUserEquip._stEquipHash.GetNextIndex(i))
    {
        if (stUserEquip._stEquipHash[i]._uiPartnerId == uiRoleId)
        {
            iRet = astEquip.AddOneItem(stUserEquip._stEquipHash[i]);
            if (iRet < 0)
            {
                return iRet;
            }
        }
    }

    return 0;
}

//为招募的伙伴穿初始装备
int CEquipMgr::WearEquip(CPlayerDetailInfo & stPlayerDetail, CUserEquip& stUserEquip, unsigned int uiEquipCfgID, short shResID, unsigned int &uiEquipID)
{
    uiEquipID = 0;
    CSingleEquip stSingleEquip;
    int iRet = CreateEquip(stUserEquip, uiEquipCfgID, stSingleEquip);
    CHECK_RETURN(iRet);

    iRet = WearEquip(stUserEquip, stSingleEquip._uiEquipID, shResID);
    if (iRet)
    {
        CT_ERROR(("%d, %d", stUserEquip._uiGID, iRet));
        return iRet;
    }

    iRet = GetData(stUserEquip, stPlayerDetail._stUserEquip);
    if (iRet)
    {
        CT_ERROR(("%d, %d", stUserEquip._uiGID, iRet));
        return iRet;
    }

    uiEquipID = stSingleEquip._uiEquipID;
    return 0;
}

//从背包中穿装备
int CEquipMgr::WearEquip(CUserEquip& stUserEquip, unsigned int uiEquipID, unsigned int uiPartnerId)
{
    uint64 ui64EquipKey = MakeEquipKey(stUserEquip._uiGID, uiEquipID);
    int iIndex = stUserEquip._stEquipHash.HashFind(ui64EquipKey);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }

    CSingleEquip& stEquip = stUserEquip._stEquipHash[iIndex];
    if (stEquip.IsWeared())
    {
        return ERROR_EQUIP_ALREADY_WEARED;
    }

    stEquip._uiPartnerId = uiPartnerId;
    return 0;
}

int CEquipMgr::TakeOffEquip(CUserEquip& stUserEquip, unsigned int uiEquipID)
{
    uint64 ui64EquipKey = MakeEquipKey(stUserEquip._uiGID, uiEquipID);
    int iIndex = stUserEquip._stEquipHash.HashFind(ui64EquipKey);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }

    CSingleEquip& stEquip = stUserEquip._stEquipHash[iIndex];
    if (!stEquip.IsWeared())
    {
        return ERROR_EQUIP_ALREADY_TAKEOFF;
    }

    stEquip._uiPartnerId = INVALID_PARTNER_ID;
    return 0;
}

int CEquipMgr::CreateEquip(CUserEquip &stUserEquip, unsigned int uiEquipCfgId, CSingleEquip& stEquip)
{
    unsigned int uiEquipId = stUserEquip.GetEquipId(uiEquipCfgId);
    return stUserEquip.CreateEquip(uiEquipId, uiEquipCfgId, SYS_DEFAULT_EQUIP_STRENGTH_LEVEL, stEquip);
}

int CEquipMgr::GetEquipSellPrice(unsigned int uiEquipCfgId, unsigned int uiStrength, int & iSilverPrice)
{
    //读配置
    CEquipConfigData   stConfigData;
    CEquipStrengthCfg  stStrengthCfg;
    int iRet = _stEquipConfig.GetConfigData(uiEquipCfgId, stConfigData);
    CHECK_RETURN(iRet);

    stStrengthCfg._stKey._usEquipLevel = stConfigData._ucEquipLevel;
    stStrengthCfg._stKey._usCurStrengthLevel = uiStrength;

    iRet = _stEquipConfig.GetStrengthConfig(stStrengthCfg._stKey, stStrengthCfg);
    CHECK_RETURN(iRet);

    iSilverPrice = stConfigData._uiSilverSellPrice + (stStrengthCfg._iSellPrice * _stEquipConfig._stEquipPriceCoef[stConfigData._ucEquipPos])/10;
    return 0;
}

int CEquipMgr::AddBuyBackEquip(CShopBuyBackItem& stBuyBackItem, CUserEquip& stUserEquip, CUserStorage & stUserStorage)
{
    int iRet = 0;

    //检查背包是否已满
    if (stUserStorage.BagIsFull())
    {
        return ERROR_STORAGE_BAG_IS_FULL;
    }

    CSingleEquip stEquip;
    unsigned int uiEquipID = stBuyBackItem._uiItemID;
    iRet = stUserEquip.CreateEquip(uiEquipID, stBuyBackItem._uiItemConfigId, stBuyBackItem._usLevel, stEquip);
    CHECK_RETURN(iRet);

    //恢复装备其他属性
    int iEquipIndex = stUserEquip.GetEquipIndex(uiEquipID);
    if (iEquipIndex >= 0)
    {
        CSingleEquip & stTargetEquip = stUserEquip.GetEquip(iEquipIndex);
        stTargetEquip._stRefineAndBlessStats = stBuyBackItem._stRefineAndBlessStats;
    }
    else
    {
        CT_ERROR(("gid = %u, equip id = %u", stUserEquip._uiGID, uiEquipID));
    }

   //在背包中保存装备的信息
    iRet = CMainCtrl::m_pstMain->m_stStorageMgr.AddItem(stUserStorage, ITEM_TYPE_EQUIP, stEquip._uiEquipID, 1);
    CHECK_RETURN(iRet);

    return 0;
}

int CEquipMgr::AddEquip(CUserEquip& stUserEquip, unsigned short usEquipConfigID, CUserStorage & stUserStorage, unsigned int & uiEquipID)
{
    int iRet = 0;
    short shCount = 1;

    //检查背包是否已满
    if (stUserStorage.BagIsFull())
    {
        return ERROR_STORAGE_BAG_IS_FULL;
    }

    iRet = stUserEquip.CheckBeforeAdd(usEquipConfigID);
    CHECK_RETURN(iRet);

    CSingleEquip stSingleEquip;
    iRet = CreateEquip(stUserEquip, usEquipConfigID, stSingleEquip);
    CHECK_RETURN(iRet);

    uiEquipID = stSingleEquip._uiEquipID;

    //在背包中保存装备的信息
    CStorageMgr & stStorageMgr =  CMainCtrl::m_pstMain->m_stStorageMgr;
    iRet = stStorageMgr.AddItem(stUserStorage, ITEM_TYPE_EQUIP, stSingleEquip._uiEquipID, shCount);
    CHECK_RETURN(iRet);

    return 0;
}

int CEquipMgr::DelEquip(CUserEquip& stUserEquip, unsigned int uiEquipID)
{
    uint64 ui64EquipKey = MakeEquipKey(stUserEquip._uiGID, uiEquipID);
    int iIndex = stUserEquip._stEquipHash.HashFind(ui64EquipKey);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }

    CSingleEquip & stSingleEquip = stUserEquip._stEquipHash[iIndex];
    int iRet = CheckEquipAddOns(stSingleEquip);
    if (iRet)
    {
        CT_ERROR(("DelEquip: %d, ret: %d", stSingleEquip._uiEquipID, iRet));
        return iRet;
    }

    //OSS账单
    unsigned short usEquipConfigID = 0;
    GetConfigIdByEquipId(uiEquipID, usEquipConfigID);
    CMainCtrl::m_pstMain->m_stOssMgr.AddConsumeItem(ITEM_TYPE_EQUIP, usEquipConfigID, 1, uiEquipID);

    CT_TRACE(("DelEquip: %d, uiEquipID: %d", stUserEquip._uiGID, uiEquipID));
    return stUserEquip._stEquipHash.HashFreeByIndex(iIndex);
}

int CEquipMgr::GetEquip(CUserEquip& stUserEquip, unsigned int uiEquipID, CSingleEquip& stEquip)
{
    uint64 ui64EquipKey = MakeEquipKey(stUserEquip._uiGID, uiEquipID);
    int iIndex = stUserEquip._stEquipHash.HashFind(ui64EquipKey);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }

    stEquip = stUserEquip._stEquipHash[iIndex];
    return 0;
}

int CEquipMgr::StrengthenEquip(CUserEquip& stUserEquip, unsigned int uiEquipID, int &iSilverPrice)
{
    uint64 ui64EquipKey = MakeEquipKey(stUserEquip._uiGID, uiEquipID);
    int iIndex = stUserEquip._stEquipHash.HashFind(ui64EquipKey);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }

    CSingleEquip & stSingleEquip = stUserEquip._stEquipHash[iIndex];

    //读配置
    CEquipConfigData   stConfigData;
    CEquipStrengthCfg  stStrengthCfg;
    int iRet = _stEquipConfig.GetConfigData(stSingleEquip._usEquipConfigID, stConfigData);
    CHECK_RETURN(iRet);

    stStrengthCfg._stKey._usEquipLevel = stConfigData._ucEquipLevel;
    stStrengthCfg._stKey._usCurStrengthLevel = stSingleEquip._usStrengthenLevel;
    iRet = _stEquipConfig.GetStrengthConfig(stStrengthCfg._stKey, stStrengthCfg);
    CHECK_RETURN(iRet);

    iSilverPrice = (stStrengthCfg._iStrengthPrice * (_stEquipConfig._stEquipPriceCoef[stConfigData._ucEquipPos]))/10;
    stSingleEquip._usStrengthenLevel += 1;
    return 0;
}

int CEquipMgr::GetConfigIdByEquipId(unsigned int uiEquipId, unsigned short &usConfigId)
{
    if (uiEquipId < EQUIP_CONFIG_ID_MOD)
    {
         usConfigId = (unsigned short)uiEquipId;
    }
    else
    {
        usConfigId = (unsigned short)(uiEquipId/EQUIP_CONFIG_ID_MOD);
    }

    return 0;
}

int CEquipMgr::GetNewEquipStrength(unsigned short usCurStrength, unsigned short &usNewStrength)
{
    if (usCurStrength > MAX_EQUIP_STRENGTH_LEVEL ||  usCurStrength < SYS_DEFAULT_EQUIP_STRENGTH_LEVEL)
    {
        return ERROR_EQUIP_WRONG_STRENGTH;
    }

    usNewStrength = (usCurStrength <=  SYS_DEFAULT_EQUIP_DESC_LEVEL) ?
                     SYS_DEFAULT_EQUIP_STRENGTH_LEVEL : (usCurStrength - SYS_DEFAULT_EQUIP_DESC_LEVEL);
    return 0;
}

int CEquipMgr::MakeEquip (CUserEquip & stUserEquip, CScrollConfigData &stScrollConfig, CSingleEquip& stEquip)
{
    int iRet;

    CSingleEquip stOldEquip = stEquip;

    unsigned short usNewEquipStrength;
    iRet = GetNewEquipStrength(stOldEquip._usStrengthenLevel, usNewEquipStrength);
    CHECK_RETURN(iRet);

    //先删除
    stUserEquip.DelEquip(stOldEquip._uiEquipID);

    //后增加
    unsigned int uiNewEquipID = stUserEquip.GetEquipId( stScrollConfig._usNewEquipConfigID);

    iRet = stUserEquip.CreateEquip(uiNewEquipID, stScrollConfig._usNewEquipConfigID, usNewEquipStrength, stEquip);
    CHECK_RETURN(iRet);
        
    int iNewIndex = stUserEquip.GetEquipIndex(uiNewEquipID);
    if (iNewIndex < 0)
    {
        CT_ERROR(("%d", stEquip._uiEquipID));
        return ERROR_EQUIP_NOT_EXIST;
    }

    for (int i = 0; i < MAX_EQUIP_CRYSTAL_NUM; i++)
    {
        stUserEquip._stEquipHash[iNewIndex]._aucCrystalID[i] = stOldEquip._aucCrystalID[i];        
    }

    //保存洗练和祝福属性
    stUserEquip._stEquipHash[iNewIndex]._stRefineAndBlessStats = stOldEquip._stRefineAndBlessStats;

    CEquipConfigData stNewEquipConfigData;
    if (RET_OK == GetConfigData(stEquip._uiEquipID, stNewEquipConfigData))
    {        
        //发送跑马灯
        if (stNewEquipConfigData._usUseLevel >= CMainCtrl::m_pstMain->GetWorldLevel() - 20)
        {
            MsgTips stTips;
            stTips.set_type(1003);
            stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(stUserEquip._uiGID));
            stTips.add_tip_argument(CTStringUtils::IntToString(stNewEquipConfigData._usEquipConfigID));
            CMainCtrl::m_pstMain->SendOnlineTips(stTips);
        }
    }

    return 0;
}

int CEquipMgr::InsetCrystal(CPlayerDetailInfo & stPlayerDetailInfo, CPlayerOnlineData & stPlayerOnlineData, unsigned char ucCrystalId, unsigned int uiEquipId, char & chCrystalPos)
{
    CUserStorage & stUserStorage = stPlayerOnlineData._stUserStorage;
    CUserEquip & stUserEquip = stPlayerOnlineData._stUserEquip;
    
    chCrystalPos = 0;

    //背包和仓库中是否存在该魔晶?    
    if (CMainCtrl::m_pstMain->m_stStorageMgr.GetItemCount(stUserStorage, ITEM_TYPE_CRYSTAL, ucCrystalId) < 0)
    {
        return ERROR_EQUIP_CRYSTAL_NONE;
    }

    CCrystalConfigData stNewCrystal;
    int iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetCrystalConfig(ucCrystalId, stNewCrystal);
    CHECK_RETURN(iRet);

    unsigned short usEquipConfigID;
    GetConfigIdByEquipId(uiEquipId, usEquipConfigID);

    CEquipConfigData stEquipConfig;
    iRet = GetConfigData(usEquipConfigID, stEquipConfig);
    CHECK_RETURN(iRet);

    //判断装备位
    iRet = stNewCrystal.IsCanWare(stEquipConfig._ucEquipPos);
    if (false == iRet)
    {
        return ERROR_EQUIP_CRYSTAL_POS;
    }

    uint64 ui64EquipKey = MakeEquipKey(stUserEquip._uiGID, uiEquipId);
    int iIndex = stUserEquip._stEquipHash.HashFind(ui64EquipKey);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }

    //检查是否已经镶嵌了相同属性
    unsigned short usToAddCrystal = 0;

    CCrystalConfigData stCrystal;
    CSingleEquip& stEquip = stUserEquip._stEquipHash[iIndex];
    int iFilledCnt = 0;
    int iSameAttrPos = -1;
    bool bCombinedCrystal = false;
    for (int i = 0; i < stEquipConfig._uicCrystalHoleNum; i++)
    {
        if (0 != stEquip._aucCrystalID[i])
        {
            iFilledCnt += 1;

            iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetCrystalConfig(stEquip._aucCrystalID[i], stCrystal);
            CHECK_RETURN(iRet);

            if (stCrystal._ucAttrType == stNewCrystal._ucAttrType)
            {                
                if (stCrystal._usLevel == stNewCrystal._usLevel)
                {
                    if (MAX_CRYSTAL_LEVLE == stCrystal._usLevel)  //达到最高的魔晶等级
                    {
                        return ERROR_WRONG_CRYSTAL_LEVEL;
                    }
                    
                    //等级相同的话, 合成新的魔晶
                    ucCrystalId = (unsigned char)stCrystal._usConstructCrystalID;
                    bCombinedCrystal = true;
                }

                else if (stCrystal._usLevel < stNewCrystal._usLevel)
                {
                    //等级比新的低, 直接替换
                    usToAddCrystal = stCrystal._usCrystalConfigID;
                    
                }
                else
                {
                    //等级比新的高, 忽略
                    return ERROR_EQUIP_CRYSTAL_ATTR;
                }

                iSameAttrPos = i;
                break;
            } 
        }
    }

    if (iFilledCnt == stEquip._aucCrystalID.GetCount() && iSameAttrPos < 0)
    {
        return ERROR_EQUIP_HOLE_FULL;
    }
    
    //取出魔晶
    iRet = CMainCtrl::m_pstMain->m_stStorageMgr.TakeOutItem(stUserStorage, ITEM_TYPE_CRYSTAL, stNewCrystal._usCrystalConfigID, 1);
    CHECK_RETURN(iRet);

    //如果是替换的话,还需要增加其它的魔晶
    if (usToAddCrystal > 0)
    {
        short shAddCnt = 1;
        iRet = stUserStorage.AddAllItem((unsigned char)ITEM_TYPE_CRYSTAL, usToAddCrystal, shAddCnt, false);
        CHECK_RETURN(iRet);
    }    

    if (iSameAttrPos >= 0)
    {
        stEquip._aucCrystalID[iSameAttrPos] = 0;
    }
    
    for (int i = 0; i < stEquipConfig._uicCrystalHoleNum; i++)
    {
        if (0 == stEquip._aucCrystalID[i])
        {
            stEquip._aucCrystalID[i] = ucCrystalId;
            chCrystalPos = i+1;
            break;
        }
    }

    if (bCombinedCrystal)
    {
        CMainCtrl::m_pstMain->m_stActMgr.TriggerCrystalCombine(stPlayerDetailInfo._stSplendidAct, stPlayerDetailInfo._uiGID, ucCrystalId, 1);
    }

    return RET_OK;
}

int CEquipMgr::UnsetCrystal(CUserEquip & stUserEquip, unsigned char ucCrystalId, unsigned int uiEquipId, char & chCrystalPos)
{
    uint64 ui64EquipKey = MakeEquipKey(stUserEquip._uiGID, uiEquipId);
    int iIndex = stUserEquip._stEquipHash.HashFind(ui64EquipKey);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }
    CSingleEquip& stEquip = stUserEquip._stEquipHash[iIndex];

    CEquipConfigData stEquipConfig;
    int iRet = GetConfigData(stEquip._usEquipConfigID, stEquipConfig);
    CHECK_RETURN(iRet);

    for (int i = 0; i < stEquipConfig._uicCrystalHoleNum; i++)
    {
        if (ucCrystalId == stEquip._aucCrystalID[i])
        {
            stEquip._aucCrystalID[i] = 0;
            chCrystalPos = i+1;
            return 0;
        }
    }

    return ERROR_EQUIP_CRYSTAL_NONE;
}

int CEquipMgr::GetEquipInfo(unsigned int uiGid, CPlayerEquipData & stEquip, MsgGridItemInfo & stGridItemInfo)
{
    CStorageGrid stGrid;
    stGrid._stKey._ucItemType = ITEM_TYPE_EQUIP;
    stGrid._stKey._uiItemID = stEquip._iEquipID;
    stGrid._stKey._usStorePos = stEquip._iPos;
    stGrid._shCount = 1;

    CMainCtrl::m_pstMain->m_stStorageMgr.GetGridInfo(uiGid, stGrid, stGridItemInfo);

    return RET_OK;
}

int CEquipMgr::GetEquipInfo(CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnlineData, unsigned int uiRoleId, MsgAnsUserStorageInfo& stAns)
{
    stAns.set_gid(stPlayerOnlineData._uiGID);
    stAns.set_storage_type(STORAGE_TYPE_ROLE_EQUIP);
    stAns.set_grid_total_num(MAX_PARTNER_EQUIP_NUM);
    stAns.set_grid_default_num(MAX_PARTNER_EQUIP_NUM);
    stAns.set_grid_unlocked_num(0);

    return GetEquipInfo (stPlayerDetail, stPlayerOnlineData, uiRoleId, *stAns.mutable_grid_items());
}

int CEquipMgr::GetEquipInfo(CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnlineData, unsigned int uiRoleId, ::google::protobuf::RepeatedPtrField<MsgGridItemInfo>& stEquips)
{
    int iRet = 0;
    CEquipMgr::T_EQUIP_ITEMS astEquip;

    CTLib::CTArray<CPlayerEquipData, MAX_PARTNER_EQUIP_NUM> astEquipDatas;

    if (uiRoleId == 0) //主角
    {
        iRet = stPlayerDetail._stPlayerEquip.GetEquipList(astEquipDatas);
    }
    else
    {
        iRet = stPlayerDetail._stUserPartner.GetEquipList((short)uiRoleId, astEquipDatas);
    }
    CHECK_RETURN(iRet);

    for (int i = 0; i < astEquipDatas.Size(); ++i)
    {
        GetEquipInfo (stPlayerOnlineData._uiGID, astEquipDatas[i], *(stEquips.Add()));
    }

    return 0;
}

//向前台推送角色装备信息
void CEquipMgr::SendEquipInfoToFront(CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnlineData,
			   	unsigned int uiRoleId, PBMsgHead stMsgHead, CEnpNetHead stEnpHead)
{
    int iRet = 0;
    stMsgHead.set_msgid(ID_MAIN_GET_USER_STORAGE_INFO);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    MsgAnsUserStorageInfo stAns;
    iRet = GetEquipInfo(stPlayerDetail, stPlayerOnlineData, uiRoleId, stAns);
    if (iRet != RET_OK)
    {
        CT_WARNING(("SendEquipInfoToFront ret %d", iRet));
        return;
    }

    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();
    CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
    CMainCtrl::m_pstMain->EncodePBMsg(stAns, CMainCtrl::m_pstMain->m_stEncodeBuf);

    CMainCtrl::m_pstMain->AnswerToClient(stEnpHead, CMainCtrl::m_pstMain->m_stEncodeBuf);

}

void CEquipMgr::GetEquipDetailInfo(CPlayerOnlineData& stPlayerOnlineData, const ::google::protobuf::RepeatedField<int64>& stReqIDList,
                                        MsgAnsItemDetailInfos& stAns)
{
    int iRet = 0;
    stAns.set_gid(stPlayerOnlineData._uiGID);
    stAns.set_item_type(ITEM_TYPE_EQUIP);

    for (int i = 0; i < stReqIDList.size(); ++i)
    {
        unsigned int uiEquipId = CT_UINT64_LOW(stReqIDList.Get(i));

        CSingleEquip stSingleEquip;
        iRet = GetEquip(stPlayerOnlineData._stUserEquip, uiEquipId, stSingleEquip);
        if (iRet != RET_OK)
        {
            CT_ERROR(("get equip error, ret %d, uid %u equipid %u", iRet, stPlayerOnlineData._uiGID, uiEquipId));
        }
        else
        {

            CEquipConfigData stEquipConfigData;
            iRet = GetConfigData(stSingleEquip._usEquipConfigID, stEquipConfigData);
            if (iRet)
            {
                CT_ERROR(("get equip config error, ret %d, uid %u equipid %u", iRet, stPlayerOnlineData._uiGID, uiEquipId));
                continue;
            }

            int iSilver = 0;
            iRet = GetEquipStrengthPrice(stSingleEquip._usEquipConfigID, stSingleEquip._usStrengthenLevel, iSilver);
            if (iRet != RET_OK)
            {
                CT_ERROR(("get GetEquipStrengthPrice error, ret %d, configid: %u, strength: %u", iRet, stSingleEquip._usEquipConfigID, stSingleEquip._usStrengthenLevel));
                continue;
            }

            MsgEquipDetailInfo * pstEquip = stAns.add_equip_infos();
            pstEquip->set_gid(stPlayerOnlineData._uiGID);
            uint64 aux = CT_UINT64_MAKE(stPlayerOnlineData._uiGID, uiEquipId);
            pstEquip->set_equip_id(CTStringUtils::Uint64ToString(aux, 10));
            pstEquip->set_equip_config_id(stSingleEquip._usEquipConfigID);
            pstEquip->set_strengthen_level(stSingleEquip._usStrengthenLevel);

            pstEquip->set_strengthen_price(iSilver);
            pstEquip->set_crystal_id1(stSingleEquip._aucCrystalID[0]);
            pstEquip->set_crystal_id2(stSingleEquip._aucCrystalID[1]);
            pstEquip->set_crystal_id3(stSingleEquip._aucCrystalID[2]);

            MsgEquipAttr stEquipAttr;
            CSingleEquipAttr stSingleEquipAttr;
            GetEquipAttr(stSingleEquip._usEquipConfigID, stSingleEquip._usStrengthenLevel, stSingleEquipAttr);
            stEquipAttr.set_strength_level(stSingleEquip._usStrengthenLevel);
            for (int k = 0; k < stSingleEquipAttr._stSingleEquipAttr.Size(); k++)
            {
                MsgTypeValuePair * pstTypeValue = stEquipAttr.add_fight_attrs();
                pstTypeValue->set_type(stSingleEquipAttr._stSingleEquipAttr[k]._ucType);
                pstTypeValue->set_value(stSingleEquipAttr._stSingleEquipAttr[k]._iValue);
            }

            *(pstEquip->mutable_equip_attr()) = stEquipAttr;
            unsigned char ucSuiteId;
            T_EQUIP_SUITE_ATTR stSuiteAttr;
            GetSingleEquipSuiteAttr (stPlayerOnlineData._stUserEquip, uiEquipId, ucSuiteId, stSuiteAttr);
            pstEquip->set_suit_id(ucSuiteId);
            pstEquip->set_suit_cnt((stSuiteAttr.Size() + 1));
            for (int j = 0; j < stSuiteAttr.Size(); j++)
            {
                MsgTypeValuePair * pstTypeValue = pstEquip->add_suit_attrs();
                pstTypeValue->set_type(stSuiteAttr[j]._ucType);
                pstTypeValue->set_value(stSuiteAttr[j]._iValue);
            }

            int iSellSilver = 0;
            GetEquipSellPrice(stSingleEquip._usEquipConfigID, stSingleEquip._usStrengthenLevel, iSellSilver);
            pstEquip->set_sell_silver(iSellSilver);

            int iFighting = 0;
            GetEquipFighting(stSingleEquip, iFighting);
            pstEquip->set_point(iFighting);

            //洗练和祝福属性
            if (stEquipConfigData._iRefineAttrCount > 0) //可洗练的装备
            {
                for (int i = 0; i < stEquipConfigData._iRefineAttrCount
                    && stSingleEquip._stRefineAndBlessStats[i] > 0; ++i)
                {
                    unsigned char ucRefineAttrID = stSingleEquip._stRefineAndBlessStats[i] / 10;
                    unsigned char ucRefineLevel = stSingleEquip._stRefineAndBlessStats[i] % 10 + 1;

                    pstEquip->add_refine(_stRefineAndBlessConfig._astRefineAttrValues[ucRefineAttrID - 1][ucRefineLevel - 1] * 10000 
                        + _stRefineAndBlessConfig._astRefineAttrChange[ucRefineAttrID - 1] * 100 
                        + ucRefineLevel);
                }
            }
            else if (stEquipConfigData._iMaxBlessLevel > 0
                && stSingleEquip._stRefineAndBlessStats[1] > 0) //可祝福且已祝福的装备
            {
                unsigned char ucBlessStat = stSingleEquip._stRefineAndBlessStats[0];
                unsigned char ucBlessLevel = stSingleEquip._stRefineAndBlessStats[1];
                int iValue = _stRefineAndBlessConfig._astBlessAttrValues[ucBlessLevel - 1];

                //属性顺序：智力、体力、力量、敏捷
                CTArray<unsigned char, MAX_EQUIP_BLESS_ATTR_PER_EQUIP> astBlessAttrID;
                astBlessAttrID.AddOneItem(BASE_ATTR_INT);
                astBlessAttrID.AddOneItem(BASE_ATTR_VIT);
                astBlessAttrID.AddOneItem(BASE_ATTR_STR);
                astBlessAttrID.AddOneItem(BASE_ATTR_AGI);

                for (int i = 0; i < MAX_EQUIP_BLESS_ATTR_PER_EQUIP; ++i)
                {
                    if (ucBlessStat & 1 << i)
                    {
                        pstEquip->add_bless_value(iValue);
                    }
                    else
                    {
                        pstEquip->add_bless_value(0);
                    }
                }
            }
        }
    }
}

void CEquipMgr::SendEquipDetailInfoToFront(CPlayerOnlineData& stPlayerOnlineData, const ::google::protobuf::RepeatedField<int64>& stReqIDList,
                                                        PBMsgHead stMsgHead, CEnpNetHead stEnpHead)
{
    MsgAnsItemDetailInfos stAns;
    if (stReqIDList.size() >= 1)
    {
        unsigned int uiGid = CT_UINT64_HIGH (stReqIDList.Get(0));
        if (uiGid == stPlayerOnlineData._uiGID || uiGid == 0)
        {
            GetEquipDetailInfo(stPlayerOnlineData, stReqIDList, stAns);
        }
        else
        {
            int iIndex = CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash.HashFind(uiGid);
            if (iIndex >= 0)
            {
                GetEquipDetailInfo(CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash[iIndex], stReqIDList, stAns);
            }
            else
            {
                CT_ERROR(("user %u not in m_stPlayerOnlineDataHash", uiGid));
            }
        }
    }

    stMsgHead.set_msgact(0);
    stMsgHead.set_msgid(ID_MAIN_GET_ITEM_DETAIL_INFO);
    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();
    CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
    CMainCtrl::m_pstMain->EncodePBMsg(stAns, CMainCtrl::m_pstMain->m_stEncodeBuf);

    CMainCtrl::m_pstMain->AnswerToClient(stEnpHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
}

int CEquipMgr::CheckEquipAddOns(CSingleEquip & stSingleEquip)
{
    for (int i = 0; i < MAX_EQUIP_CRYSTAL_NUM; i++)
    {
        if (0 != stSingleEquip._aucCrystalID[i])
        {
            return ERROR_EQUIP_HAVE_ADDITION;
        }
    }

    return 0;
}

int CEquipMgr::GetEquipFighting(CSingleEquip & stSingleEquip, int & iFighting)
{
    CSingleEquipAttr stSingleEquipAttr;
    int iRet = GetEquipAttr(stSingleEquip._usEquipConfigID, stSingleEquip._usStrengthenLevel, stSingleEquipAttr);
    if (iRet)
    {
    }

    // "装备评分公式" 跟 "角色战斗力公式" 相同  “战斗系统/公式.docx”
    // 角色战斗力 = 生命上限 / 50 + (物攻+魔攻+物防+魔防)/5 +
    //             (命中等级+闪避等级+暴击等级+抗暴等级+破击等级+格挡等级+必杀等级+反伤等级+穿透等级+免伤等级+痊愈等级)/2


    //TODO: 魔晶对主角的属性加成
    CPlayerAttr stEquipAttr;
    for (int k = 0; k < stSingleEquipAttr._stSingleEquipAttr.Size(); ++k)
    {
        stEquipAttr.AddAttr(stSingleEquipAttr._stSingleEquipAttr[k]._ucType, stSingleEquipAttr._stSingleEquipAttr[k]._iValue);
    }

    //洗练和祝福属性
    CPlayerAttr stRefineAndBlessAttr;
    GetRefineAndBlessAttr(stSingleEquip, stRefineAndBlessAttr);
    stEquipAttr += stRefineAndBlessAttr;

    CMainCtrl::m_pstMain->m_stRoleMgr.CalcFighting(stEquipAttr, iFighting);
    return 0;
}

//检查装备能否进行转换. iGoldPrice保存转换需要的金币
int CEquipMgr::CheckTransform (CUserEquip & stUserEquip, unsigned int uiEquipId, unsigned short usNewConfigid)
{
    int iIndex = stUserEquip.GetEquipIndex(uiEquipId);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }
    CSingleEquip & stOldEquip = stUserEquip.GetEquip(iIndex);

    if (stOldEquip._usEquipConfigID == usNewConfigid)
    {
        CT_ERROR(("%d", stUserEquip._uiGID));
        return ERROR_EQUIP_CNOT_TRANSFORM;
    }

    CEquipConfigData stNewConfig;
    int iRet = _stEquipConfig.GetConfigData(usNewConfigid, stNewConfig);
    if (iRet)
    {
        CT_ERROR(("%d", usNewConfigid));
        return ERROR_EQUIP_NO_CONFIG;
    }

    CEquipConfigData stOldConfig;
    iRet = _stEquipConfig.GetConfigData(usNewConfigid, stOldConfig);
    if (iRet)
    {
        CT_ERROR(("%d", stOldEquip._usEquipConfigID));
        return ERROR_EQUIP_NO_CONFIG;
    }

    if (stNewConfig._ucEquipLevel != stOldConfig._ucEquipLevel
        && stNewConfig._ucEquipPos != stOldConfig._ucEquipPos
        && (EQUIP_POS_WEAPON != stNewConfig._ucEquipPos))
    {
        CT_ERROR(("%d", stNewConfig._usEquipConfigID));
        return ERROR_EQUIP_CNOT_TRANSFORM;
    }

    return 0;
}

int CEquipMgr::Transform (CUserEquip & stUserEquip, unsigned int uiEquipId, unsigned short usNewConfigid, unsigned int & uiNewEquipId)
{
    int iOldIndex = stUserEquip.GetEquipIndex(uiEquipId);
    if (iOldIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }
    CSingleEquip stOldEquip = stUserEquip.GetEquip(iOldIndex);

    //先删除
    stUserEquip.DelEquip(uiEquipId);
    
    //后增加
    int iRet = stUserEquip.CreateEquip(usNewConfigid, uiNewEquipId);
    CHECK_RETURN(iRet);

    int iNewIndex = stUserEquip.GetEquipIndex (uiNewEquipId);
    if (iNewIndex < 0)
    {
        CT_ERROR(("%d, %d",  stUserEquip._uiGID, uiNewEquipId));
        return ERROR_EQUIP_NOT_EXIST;
    }
    CSingleEquip & stNewEquip = stUserEquip.GetEquip(iNewIndex);
    
    //重新设置装备ID
    stNewEquip = stOldEquip;
    stNewEquip._usEquipConfigID = usNewConfigid;
    stNewEquip._uiEquipID = uiNewEquipId;

    return 0;
}


int CEquipMgr::GetStrengthTotalLevel (CUserEquip& stUserEquip, unsigned int uiRoleId)
{
    int iTotalLevel = 0; 
    for (int i = stUserEquip._stEquipHash.GetHeadIndex();
        i >= 0; i = stUserEquip._stEquipHash.GetNextIndex(i))
    {
        CSingleEquip & stEquip = stUserEquip._stEquipHash[i];
        if (stEquip._uiPartnerId == uiRoleId)
        {
            iTotalLevel += stEquip._usStrengthenLevel;
        }
    }

    return iTotalLevel;
}


void CEquipMgr::NotifyEquipInMap (unsigned int uiEquipId, unsigned int uiGid)
{
    unsigned short usEquipConfigID = 0;
    GetConfigIdByEquipId(uiEquipId, usEquipConfigID);

    CEquipConfigData stConfigData;
    int iRet = _stEquipConfig.GetConfigData(usEquipConfigID, stConfigData);
    if (iRet)
    {
        CT_ERROR(("%d, %d", usEquipConfigID, uiGid));
        return ;
    }

    //同步同屏数据
    unsigned char ucEquipPos = stConfigData._ucEquipPos;
    if (EQUIP_POS_WEAPON == ucEquipPos
        || EQUIP_POS_HELMET == ucEquipPos
        || EQUIP_POS_CLOTH == ucEquipPos)  //头、身体、武器才需要同步
    {
        CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(uiGid, NOTIFY_MAP_INFO);
    }
}


void CEquipMgr::UpdatePotenLevel (CPlayerBaseInfo & stBaseInfo)
{
    if (stBaseInfo._ucCrystalPotenLevel <= 0)
    {
        stBaseInfo._ucCrystalPotenLevel = 1;     //已有账号, 等级初始化为1级
    }

    int iLevelUpExp = _stEquipConfig.GetPotenLevelUpExp(stBaseInfo._ucCrystalPotenLevel);
    while (iLevelUpExp > 0 && stBaseInfo._iCrystalPotenExp >= iLevelUpExp)
    {
        stBaseInfo._ucCrystalPotenLevel += 1;
        stBaseInfo._iCrystalPotenExp -= iLevelUpExp;

        iLevelUpExp = _stEquipConfig.GetPotenLevelUpExp(stBaseInfo._iCrystalPotenExp);
    }   

    CT_TRACE(("%d, %d, %d", stBaseInfo._uiGID, stBaseInfo._ucCrystalPotenLevel, stBaseInfo._iCrystalPotenExp));
}

int CEquipMgr::GetPotenUpNeedExp (CPlayerBaseInfo & stBaseInfo)
{
    int iLevelUpExp = _stEquipConfig.GetPotenLevelUpExp(stBaseInfo._ucCrystalPotenLevel);
    return CT_MAX((iLevelUpExp - stBaseInfo._iCrystalPotenExp), 0);
}

int CEquipMgr::RefineEquipGetInfo(CUserEquip& stUserEquip, unsigned int uiEquipID, MsgAnsEquipRefine& stAns)
{
    int iRet = 0;
    int iIndex = stUserEquip.GetEquipIndex(uiEquipID);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }
    CSingleEquip& stEquip = stUserEquip.GetEquip(iIndex);

    //配置
    CEquipConfigData stEquipConfig;
    iRet = _stEquipConfig.GetConfigData(stEquip._usEquipConfigID, stEquipConfig);
    if (iRet)
    {
        CT_ERROR(("%d", stEquip._usEquipConfigID));
        return ERROR_EQUIP_NO_CONFIG;
    }

    if (stEquipConfig._iRefineAttrCount <= 0) //装备不可洗练
    {
        return 0;
    }

    //当前属性
    for (int i = 0; i < stEquipConfig._iRefineAttrCount && i < MAX_EQUIP_REFINE_ATTR_PER_EQUIP; ++i)
    {
        if (stEquip._stRefineAndBlessStats[i] == 0)
        {
            break;
        }

        unsigned char ucRefineAttrID = stEquip._stRefineAndBlessStats[i] / 10;
        unsigned char ucRefineLevel = stEquip._stRefineAndBlessStats[i] % 10 + 1;
        int iValue = _stRefineAndBlessConfig._astRefineAttrValues[ucRefineAttrID - 1][ucRefineLevel - 1];

        stAns.add_now_refine(iValue * 10000 + _stRefineAndBlessConfig._astRefineAttrChange[ucRefineAttrID - 1] * 100 + ucRefineLevel);
    }

    //未保存属性
    for (int i = 0; i < stEquipConfig._iRefineAttrCount && i < MAX_EQUIP_REFINE_ATTR_PER_EQUIP; ++i)
    {
        int iIndex = i + MAX_EQUIP_REFINE_ATTR_PER_EQUIP;
        if (stEquip._stRefineAndBlessStats[iIndex] == 0)
        {
            break;
        }

        unsigned char ucRefineAttrID = stEquip._stRefineAndBlessStats[iIndex] / 10;
        unsigned char ucRefineLevel = stEquip._stRefineAndBlessStats[iIndex] % 10 + 1;
        int iValue = _stRefineAndBlessConfig._astRefineAttrValues[ucRefineAttrID - 1][ucRefineLevel - 1];

        stAns.add_not_save_refine(iValue * 10000 + _stRefineAndBlessConfig._astRefineAttrChange[ucRefineAttrID - 1] * 100 + ucRefineLevel);
    }

    return 0;
}

int CEquipMgr::RefineEquipEnvalidAttr(CUserEquip& stUserEquip, unsigned int uiEquipID, CPlayerBaseInfo& stPlayerBaseInfo, bool& bIsWare, short& shWareRoleID)
{
    int iRet = 0;
    int iIndex = stUserEquip.GetEquipIndex(uiEquipID);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }
    CSingleEquip& stEquip = stUserEquip.GetEquip(iIndex);

    //获取配置
    CEquipConfigData stEquipConfig;
    iRet = _stEquipConfig.GetConfigData(stEquip._usEquipConfigID, stEquipConfig);
    if (iRet)
    {
        CT_ERROR(("%d", stEquip._usEquipConfigID));
        return ERROR_EQUIP_NO_CONFIG;
    }

    //检查
    if (stEquipConfig._iRefineAttrCount <= 0)
    {
        return ERROR_EQUIP_REFINE_AND_BLESS_ERROR1;
    }

    //获取目标位置
    int iDestIndex = -1;
    for (int i = 0; i < stEquipConfig._iRefineAttrCount; ++i)
    {
        if (stEquip._stRefineAndBlessStats[i] != 0)
        {
            continue;
        }

        iDestIndex = i;
        break;
    }

    if (iDestIndex < 0)
    {
        return ERROR_EQUIP_REFINE_AND_BLESS_ERROR2;
    }

    //roll属性和等级
    unsigned char ucAttrID = 0;
    unsigned char ucAttrLevel = 0;

    do 
    {
        iRet = RefineEquipRollAttrAndLevel(ucAttrID, ucAttrLevel);
        CHECK_RETURN(iRet);
    } while (ucAttrLevel > _stRefineAndBlessConfig._iRefineEnableMaxLevel || stEquip.HasRefineAttr(ucAttrID));

    if (iDestIndex > 0) //第一个属性不扣费
    {
        //扣除金币
        iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stPlayerBaseInfo, OSS_MONEY_MODULE_45, _stRefineAndBlessConfig._iRefineNeedGold);
        CHECK_RETURN(iRet);
    }

    //添加属性
    stEquip._stRefineAndBlessStats[iDestIndex] = ucAttrID * 10 + (ucAttrLevel - 1);

    //下发数据
    CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stUserEquip._uiGID, NOTIFY_USER_MONEY);

    bIsWare = stEquip.IsWeared();
    shWareRoleID = stEquip._uiPartnerId;

    return 0;
}

int CEquipMgr::RefineEquipRollAttrAndLevel(unsigned char& ucAttrID, unsigned char& ucAttrLevel)
{
    int iRet = 0;
    ucAttrID = 0;
    ucAttrLevel = 0;

    CRateTarget stAttrRateTarget;
    iRet = _stRefineAndBlessConfig._stRefineAttrDrop.DropOne(stAttrRateTarget);
    CHECK_RETURN(iRet);
    ucAttrID = stAttrRateTarget._iTargetID;

    CRateTarget stLevelRateTarget;
    iRet = _stRefineAndBlessConfig._stRefineLevelDrop.DropOne(stLevelRateTarget);
    CHECK_RETURN(iRet);
    ucAttrLevel = stLevelRateTarget._iTargetID;

    if (ucAttrID == 0 || ucAttrID > MAX_EQUIP_REFINE_ATTR)
    {
        CT_ERROR(("%d", ucAttrID));
        return RET_SYS_ERROR;
    }

    if (ucAttrLevel == 0 || ucAttrLevel > MAX_EQUIP_REFINE_LEVEL)
    {
        CT_ERROR(("%d", ucAttrLevel));
        return RET_SYS_ERROR;
    }

    return 0;
}

int CEquipMgr::RefineEquip(CPlayerOnlineData& stPlayerOnlineData, CPlayerBaseInfo& stPlayerBaseInfo, unsigned int uiEquipID, int iLockedAttrPos)
{
    int iRet = 0;
    CUserEquip& stUserEquip = stPlayerOnlineData._stUserEquip;

    int iIndex = stUserEquip.GetEquipIndex(uiEquipID);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }
    CSingleEquip& stEquip = stUserEquip.GetEquip(iIndex);

    //获取配置
    CEquipConfigData stEquipConfig;
    iRet = _stEquipConfig.GetConfigData(stEquip._usEquipConfigID, stEquipConfig);
    if (iRet)
    {
        CT_ERROR(("%d", stEquip._usEquipConfigID));
        return ERROR_EQUIP_NO_CONFIG;
    }

    if (stEquipConfig._iRefineAttrCount <= 0)
    {
        CT_ERROR((""));
        return ERROR_EQUIP_REFINE_AND_BLESS_ERROR8;
    }

    //判断
    int iNeedMaterialCount = 1; //需要材料个数
    int iNeedSilverCount = 0;   //需要银币个数
    for (int i = 0; i < MAX_EQUIP_REFINE_ATTR_PER_EQUIP
                    && stEquip._stRefineAndBlessStats[i] != 0; ++i)
    {
        iNeedSilverCount += _stRefineAndBlessConfig._iRefineUseSilverPerAttr;
        if (iLockedAttrPos & 1 << i) //锁定的属性
        {
            iNeedMaterialCount++;
        }
    }

    if (iNeedSilverCount <= 0 || iNeedMaterialCount <= 0)
    {
        CT_ERROR((""));
        return RET_SYS_ERROR;
    }

    //检查材料和银币是否足够
    int iNeedGold = 0;
    int iNowMaterialCount = CMainCtrl::m_pstMain->m_stStorageMgr.GetItemCount(stPlayerOnlineData._stUserStorage, ITEM_TYPE_MATERIAL, stEquipConfig._iRefineUseMaterial);
    if (iNowMaterialCount < iNeedMaterialCount)
    {
        iNeedGold = (iNeedMaterialCount - iNowMaterialCount) * 10;
        iNeedMaterialCount = iNowMaterialCount;
    }

    if (iNeedGold > 0 && iNeedGold > stPlayerBaseInfo._iGold)
    {
        return ERROR_EQUIP_REFINE_AND_BLESS_ERROR3;
    }

    if (stPlayerBaseInfo._i64Silver < (int64)iNeedSilverCount)
    {
        return ERROR_EQUIP_REFINE_AND_BLESS_ERROR4;
    }
 
    //扣除材料、金币和银币
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubSilver(stPlayerBaseInfo, iNeedSilverCount, 0);
    CHECK_RETURN(iRet);

    if (iNeedMaterialCount > 0)
    {
        iRet = CMainCtrl::m_pstMain->m_stStorageMgr.TakeOutItem(stPlayerOnlineData._stUserStorage, 
            ITEM_TYPE_MATERIAL, stEquipConfig._iRefineUseMaterial, iNeedMaterialCount);
        CHECK_RETURN(iRet);
    }

    iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stPlayerBaseInfo, OSS_MONEY_MODULE_46, iNeedGold);
    CHECK_RETURN(iRet);

    //洗练
    for (int i = 0; i < stEquipConfig._iRefineAttrCount
        && stEquip._stRefineAndBlessStats[i] != 0; ++i)
    {
        if (iLockedAttrPos & 1 << i) //锁定的属性
        {
            stEquip._stRefineAndBlessStats[i + MAX_EQUIP_REFINE_ATTR_PER_EQUIP] 
                =  stEquip._stRefineAndBlessStats[i];

        }
        else //非锁定的属性
        {
            unsigned char ucAttrID = 0;
            unsigned char ucAttrLevel = 0;
            iRet = RefineEquipRollAttrAndLevel(ucAttrID, ucAttrLevel);
            CHECK_RETURN(iRet);
            stEquip._stRefineAndBlessStats[i + MAX_EQUIP_REFINE_ATTR_PER_EQUIP]
                    = ucAttrID * 10 + ucAttrLevel - 1;
        }
    }

    //下发数据
    CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stUserEquip._uiGID, NOTIFY_USER_MONEY | NOTIFY_BAG_INFO);

    return 0;
}

int CEquipMgr::RefineEquipSave(CUserEquip& stUserEquip, unsigned int uiEquipID, bool& bIsWare, short& shWareRoleID)
{   
    int iIndex = stUserEquip.GetEquipIndex(uiEquipID);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }
    CSingleEquip& stEquip = stUserEquip.GetEquip(iIndex);

    CEquipConfigData stEquipConfig;
    int iRet = _stEquipConfig.GetConfigData(stEquip._usEquipConfigID, stEquipConfig);
    if (iRet)
    {
        CT_ERROR(("%d", stEquip._usEquipConfigID));
        return ERROR_EQUIP_NO_CONFIG;
    }

    if (stEquipConfig._iRefineAttrCount <= 0)
    {
        CT_ERROR((""));
        return RET_SYS_ERROR;
    }

    for (int i = 0; i < stEquipConfig._iRefineAttrCount 
        && stEquip._stRefineAndBlessStats[i] != 0; ++i)
    {
        if (stEquip._stRefineAndBlessStats[i + MAX_EQUIP_REFINE_ATTR_PER_EQUIP] == 0)
        {
            continue;
        }

        stEquip._stRefineAndBlessStats[i] = stEquip._stRefineAndBlessStats[i + MAX_EQUIP_REFINE_ATTR_PER_EQUIP];
        stEquip._stRefineAndBlessStats[i + MAX_EQUIP_REFINE_ATTR_PER_EQUIP] = 0;
    }

    //下发属性
    bIsWare = stEquip.IsWeared();
    shWareRoleID = (short)stEquip._uiPartnerId;

    return 0;
}

int CEquipMgr::BlessEquipGetInfo(CUserEquip& stUserEquip, unsigned int uiEquipID, 
                                    CPlayerDetailInfo& stPlayerDetailInfo, MsgAnsEquipBless& stAns)
{
    int iRet = 0;
    int iIndex = stUserEquip.GetEquipIndex(uiEquipID);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }
    CSingleEquip& stEquip = stUserEquip.GetEquip(iIndex);

    CEquipConfigData stEquipConfigData;
    iRet = GetConfigData(stEquip._usEquipConfigID, stEquipConfigData);
    CHECK_RETURN(iRet);

    //属性值
    if (stEquipConfigData._iMaxBlessLevel > 0
        && stEquip._stRefineAndBlessStats[1] > 0) //可祝福且已祝福的装备
    {
        unsigned char ucBlessStat = stEquip._stRefineAndBlessStats[0];
        unsigned char ucBlessLevel = stEquip._stRefineAndBlessStats[1];
        int iValue = _stRefineAndBlessConfig._astBlessAttrValues[ucBlessLevel - 1];

        //属性顺序：智力、体力、力量、敏捷
        for (int i = 0; i < MAX_EQUIP_BLESS_ATTR_PER_EQUIP; ++i)
        {
            if (ucBlessStat & 1 << i)
            {
                stAns.add_bless_value(iValue);
            }
            else
            {
                stAns.add_bless_value(0);
            }
        }

        //祝福等级
        stAns.set_bless_level(ucBlessLevel);
    }

    //祝福点
    stAns.set_bless_point(stPlayerDetailInfo._stUserEquip._iBlessPoint);

    return 0;
}

int CEquipMgr::BlessEquip(CUserEquip& stUserEquip, unsigned int uiEquipID, CPlayerBaseInfo& stPlayerBaseInfo, 
                          CPlayerDetailInfo& stPlayerDetailInfo, bool& bIsWare, short& shWareRoleID)
{
    int iIndex = CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash.HashFind(stPlayerBaseInfo._uiGID);
    if (iIndex < 0)
    {
        CT_ERROR((""));
        return RET_SYS_ERROR;
    }
    CPlayerOnlineData& stPlayerOnlineData = CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash[iIndex];
    CUserStorage& stUserStorage = stPlayerOnlineData._stUserStorage;

    int iRet = 0;
    iIndex = stUserEquip.GetEquipIndex(uiEquipID);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }
    CSingleEquip& stEquip = stUserEquip.GetEquip(iIndex);

    CEquipConfigData stEquipConfig;
    iRet = _stEquipConfig.GetConfigData(stEquip._usEquipConfigID, stEquipConfig);
    if (iRet)
    {
        CT_ERROR(("%d", stEquip._usEquipConfigID));
        return ERROR_EQUIP_NO_CONFIG;
    }

    if (stEquipConfig._iMaxBlessLevel <= 0)
    {
        CT_ERROR((""));
        return RET_SYS_ERROR;
    }

    unsigned char& stBlessStat = stEquip._stRefineAndBlessStats[0];

    //是否首次祝福
    bool bIsFirstBless = (0 == stBlessStat);

    //先扣除道具
    if (stUserStorage.GetItemCount(ITEM_TYPE_MATERIAL, 208) > 0)
    {
        iRet = CMainCtrl::m_pstMain->m_stStorageMgr.TakeOutItem(stPlayerOnlineData._stUserStorage, ITEM_TYPE_MATERIAL, 208, 1);
        CHECK_RETURN(iRet);

        CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stPlayerBaseInfo._uiGID, NOTIFY_BAG_INFO);
    }
    else
    {
        if (stPlayerBaseInfo._iGold < _stRefineAndBlessConfig._iBlessUseGold)
        {
            return ERROR_GOLD_LESS;
        }

        //扣除金币
        iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stPlayerBaseInfo, OSS_MONEY_MODULE_45, _stRefineAndBlessConfig._iBlessUseGold);
        CHECK_RETURN(iRet);
        CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stPlayerBaseInfo._uiGID, NOTIFY_USER_MONEY);
    }

    //祝福
    CTArray<unsigned char, MAX_EQUIP_BLESS_ATTR_PER_EQUIP> aucAllAttr;
    aucAllAttr.AddOneItem((unsigned char)(1 << 0));
    aucAllAttr.AddOneItem((unsigned char)(1 << 1));
    aucAllAttr.AddOneItem((unsigned char)(1 << 2));
    aucAllAttr.AddOneItem((unsigned char)(1 << 3));

    int iNowAttrCount = 0;
    int iGetBlessPointCount = 0; //获得的祝福点数量
    stBlessStat = 0;
    for (int i = 0; i < _stRefineAndBlessConfig._astBlessRate.Size(); ++i)
    {
        if (bIsFirstBless && iNowAttrCount >= _stRefineAndBlessConfig._iBlessFirstHasAttrCount)
        {
            break;
        }

        if (CT_RANDOM_NUM->GetRand(COMM_MOD) < _stRefineAndBlessConfig._astBlessRate[i])
        {
            iNowAttrCount++;
            int iAttrIndex = CT_RANDOM_NUM->GetRand(aucAllAttr.Size());
            stBlessStat += aucAllAttr[iAttrIndex];
            aucAllAttr.DelOneItem(iAttrIndex);
            iGetBlessPointCount += MAX_EQUIP_BLESS_POINT_PER_ATTR;
        }
    }

    //增加祝福点
    stPlayerDetailInfo._stUserEquip._iBlessPoint += iGetBlessPointCount;

    //设置祝福等级
    if (bIsFirstBless)
    {
        stEquip._stRefineAndBlessStats[1] = 1;
    }

    bIsWare = stEquip.IsWeared();
    shWareRoleID = stEquip._uiPartnerId;

    return 0;
}

int CEquipMgr::BlessEquipLevelUp(CUserEquip& stUserEquip, unsigned int uiEquipID, CPlayerDetailInfo& stPlayerDetailInfo,
                                 bool& bIsWare, short& shWareRoleID)
{
    int iRet = 0;
    int iIndex = stUserEquip.GetEquipIndex(uiEquipID);
    if (iIndex < 0)
    {
        return ERROR_EQUIP_NOT_EXIST;
    }
    CSingleEquip& stEquip = stUserEquip.GetEquip(iIndex);

    CEquipConfigData stEquipConfig;
    iRet = _stEquipConfig.GetConfigData(stEquip._usEquipConfigID, stEquipConfig);
    if (iRet)
    {
        CT_ERROR(("%d", stEquip._usEquipConfigID));
        return ERROR_EQUIP_NO_CONFIG;
    }

    if (stEquipConfig._iMaxBlessLevel <= 0)
    {
        CT_ERROR((""));
        return RET_SYS_ERROR;
    }

    unsigned char& ucNowBlessLevel = stEquip._stRefineAndBlessStats[1];
    if (ucNowBlessLevel == 0) //未初始化
    {
        return ERROR_EQUIP_REFINE_AND_BLESS_ERROR5;
    }

    if (ucNowBlessLevel >= CT_MIN(MAX_EQUIP_BLESS_LEVEL, stEquipConfig._iMaxBlessLevel))
    {
        return ERROR_EQUIP_REFINE_AND_BLESS_ERROR6;
    }

    //判断
    int iLevelUpNeedPoint = _stRefineAndBlessConfig._astBlessNeedPoint[ucNowBlessLevel - 1];
    if (stPlayerDetailInfo._stUserEquip._iBlessPoint < iLevelUpNeedPoint)
    {
        return ERROR_EQUIP_REFINE_AND_BLESS_ERROR7;
    }

    //升级
    stPlayerDetailInfo._stUserEquip._iBlessPoint -= iLevelUpNeedPoint;
    ucNowBlessLevel++;

    bIsWare = stEquip.IsWeared();
    shWareRoleID = stEquip._uiPartnerId;

    return 0;
}
